@etsoo/materialui 1.3.31 → 1.3.33

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.
@@ -2,7 +2,7 @@ import { Autocomplete } from "@mui/material";
2
2
  import React from "react";
3
3
  import { globalApp } from "./app/ReactApp";
4
4
  import { InputField } from "./InputField";
5
- import { MUUtils } from "./MUUtils";
5
+ import { DataTypes } from "@etsoo/shared";
6
6
  export function ComboBoxPro(props) {
7
7
  var _a;
8
8
  // Labels
@@ -53,7 +53,7 @@ export function ComboBoxPro(props) {
53
53
  if (!localValue && localValue != value)
54
54
  onChange(event, value, "blur", undefined);
55
55
  }
56
- } })), getOptionLabel: (item) => typeof item === "object" ? MUUtils.getListItemLabel(item) : item, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, onChange: (event, value, reason, details) => {
56
+ } })), getOptionLabel: (item) => typeof item === "object" ? DataTypes.getListItemLabel(item) : item, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, onChange: (event, value, reason, details) => {
57
57
  setValue(value);
58
58
  if (onChange)
59
59
  onChange(event, value, reason, details);
package/lib/MUUtils.d.ts CHANGED
@@ -1,15 +1,8 @@
1
- import { ListType2 } from "@etsoo/shared";
2
1
  import { GridApiCommunity } from "@mui/x-data-grid/models/api/gridApiCommunity";
3
2
  /**
4
3
  * MU utilities
5
4
  */
6
5
  export declare namespace MUUtils {
7
- /**
8
- * Get ListType2 item label
9
- * @param item Item
10
- * @returns Result
11
- */
12
- function getListItemLabel(item: ListType2): string;
13
6
  /**
14
7
  * Get grid data
15
8
  * @param grid Grid
package/lib/MUUtils.js CHANGED
@@ -3,19 +3,6 @@
3
3
  */
4
4
  export var MUUtils;
5
5
  (function (MUUtils) {
6
- /**
7
- * Get ListType2 item label
8
- * @param item Item
9
- * @returns Result
10
- */
11
- function getListItemLabel(item) {
12
- return "label" in item
13
- ? item.label
14
- : "name" in item
15
- ? item.name
16
- : item.title;
17
- }
18
- MUUtils.getListItemLabel = getListItemLabel;
19
6
  /**
20
7
  * Get grid data
21
8
  * @param grid Grid
@@ -0,0 +1,80 @@
1
+ import { DataTypes, IdDefaultType, LabelDefaultType, ListType } from "@etsoo/shared";
2
+ import { FormControlProps } from "@mui/material";
3
+ import React from "react";
4
+ /**
5
+ * OptionGroupFlag methods ref
6
+ */
7
+ export interface OptionGroupFlagRef {
8
+ /**
9
+ * Disable specific items with their ids
10
+ * @param ids Ids
11
+ */
12
+ disable(ids: number[]): void;
13
+ }
14
+ /**
15
+ * OptionGroupFlag props
16
+ */
17
+ export type OptionGroupFlagProps<T extends object, D extends DataTypes.Keys<T, number>, L extends DataTypes.Keys<T, string>> = Omit<FormControlProps<"fieldset">, "defaultValue"> & {
18
+ /**
19
+ * Default value
20
+ */
21
+ defaultValue?: T[D] & number;
22
+ /**
23
+ * Get option label function
24
+ */
25
+ getOptionLabel?: (option: T) => string;
26
+ /**
27
+ * Id field
28
+ */
29
+ idField?: D;
30
+ /**
31
+ * Label
32
+ */
33
+ label?: string;
34
+ /**
35
+ * Label field
36
+ */
37
+ labelField?: L;
38
+ /**
39
+ * Methods
40
+ */
41
+ mRef?: React.Ref<OptionGroupFlagRef>;
42
+ /**
43
+ * Field name
44
+ */
45
+ name: string;
46
+ /**
47
+ * On value change handler
48
+ */
49
+ onValueChange?: (value?: T[D] & number) => void;
50
+ /**
51
+ * Array of options.
52
+ */
53
+ options: ReadonlyArray<T>;
54
+ /**
55
+ * Is the field read only?
56
+ */
57
+ readOnly?: boolean;
58
+ /**
59
+ * Display group of elements in a compact row
60
+ */
61
+ row?: boolean;
62
+ /**
63
+ * Item size
64
+ */
65
+ itemSize?: "small" | "medium";
66
+ /**
67
+ * Item height in px
68
+ */
69
+ itemHeight?: number;
70
+ /**
71
+ * Helper text
72
+ */
73
+ helperText?: React.ReactNode;
74
+ };
75
+ /**
76
+ * OptionGroupFlag
77
+ * @param props Props
78
+ * @returns Component
79
+ */
80
+ export declare function OptionGroupFlag<T extends object = ListType, D extends DataTypes.Keys<T, number> = IdDefaultType<T, number>, L extends DataTypes.Keys<T, string> = LabelDefaultType<T>>(props: OptionGroupFlagProps<T, D, L>): React.JSX.Element;
@@ -0,0 +1,95 @@
1
+ import { DataTypes, Utils } from "@etsoo/shared";
2
+ import { Box, Checkbox, FormControl, FormControlLabel, FormGroup, FormHelperText, InputLabel } from "@mui/material";
3
+ import NotchedOutline from "@mui/material/OutlinedInput";
4
+ import React from "react";
5
+ /**
6
+ * OptionGroupFlag
7
+ * @param props Props
8
+ * @returns Component
9
+ */
10
+ export function OptionGroupFlag(props) {
11
+ // Destruct
12
+ const { getOptionLabel, defaultValue, idField = "id", label, labelField = "label", mRef, name, onValueChange, options, readOnly, row, itemSize, itemHeight = row ? 56 : 42, helperText, variant, required, fullWidth, sx = {}, ...rest } = props;
13
+ // Outlined
14
+ const outlined = variant === "outlined";
15
+ if (sx) {
16
+ Object.assign(sx, {
17
+ height: outlined
18
+ ? row
19
+ ? `${itemHeight}px`
20
+ : `${options.length * itemHeight + 14}px`
21
+ : undefined
22
+ });
23
+ }
24
+ // Get option value
25
+ // D type should be the source id type
26
+ const getOptionValue = (option) => {
27
+ const value = DataTypes.getValue(option, idField);
28
+ if (value == null)
29
+ return null;
30
+ return value;
31
+ };
32
+ // Value
33
+ const [value, setValue] = React.useState(defaultValue);
34
+ React.useEffect(() => {
35
+ setValue(defaultValue);
36
+ }, [defaultValue]);
37
+ // Disabled ids
38
+ const [disabledIds, setDisabledIds] = React.useState();
39
+ // Item checked
40
+ const itemChecked = (option) => {
41
+ // Value
42
+ const itemValue = getOptionValue(option);
43
+ if (itemValue == null || value == null)
44
+ return false;
45
+ return (value & itemValue) > 0;
46
+ };
47
+ React.useImperativeHandle(mRef, () => ({
48
+ disable(ids) {
49
+ setDisabledIds(ids);
50
+ }
51
+ }));
52
+ // First item value
53
+ const firstOptionValue = getOptionValue(options[0]);
54
+ // Items
55
+ const list = options.map((option) => {
56
+ // Value
57
+ const ov = getOptionValue(option);
58
+ if (ov == null)
59
+ return;
60
+ // Control
61
+ const control = (React.createElement(Checkbox, { name: name, readOnly: readOnly, size: itemSize, checked: itemChecked(option), disabled: disabledIds === null || disabledIds === void 0 ? void 0 : disabledIds.includes(ov), onChange: (event) => {
62
+ if (firstOptionValue == null)
63
+ return;
64
+ const typeValue = Utils.parseString(event.target.value, firstOptionValue);
65
+ const newValue = (value == null
66
+ ? event.target.checked
67
+ ? typeValue
68
+ : undefined
69
+ : event.target.checked
70
+ ? value | typeValue
71
+ : value ^ typeValue);
72
+ if (onValueChange)
73
+ onValueChange(newValue);
74
+ setValue(newValue);
75
+ } }));
76
+ // Label
77
+ const label = getOptionLabel == null ? `${option[labelField]}` : getOptionLabel(option);
78
+ return (React.createElement(FormControlLabel, { key: ov, control: control, value: ov, label: label }));
79
+ });
80
+ // Layout
81
+ return (React.createElement(React.Fragment, null,
82
+ React.createElement(FormControl, { component: "fieldset", fullWidth: fullWidth, sx: sx, ...rest },
83
+ label && (React.createElement(InputLabel, { required: required, variant: variant, shrink: true }, label)),
84
+ outlined && (React.createElement(NotchedOutline, { label: label && required ? label + " *" : label, notched: true, sx: {
85
+ cursor: "default",
86
+ position: "absolute",
87
+ width: fullWidth ? "100%" : "auto",
88
+ "& input": {
89
+ visibility: "hidden"
90
+ }
91
+ } })),
92
+ React.createElement(Box, { paddingLeft: 2, paddingY: "7px", position: outlined ? "absolute" : undefined },
93
+ React.createElement(FormGroup, { row: row }, list))),
94
+ helperText && (React.createElement(FormHelperText, { sx: { marginLeft: 2, marginRight: 2 } }, helperText))));
95
+ }
package/lib/QuickList.js CHANGED
@@ -1,9 +1,9 @@
1
+ import { DataTypes } from "@etsoo/shared";
1
2
  import { LinearProgress, List, ListItem, ListItemButton, Typography } from "@mui/material";
2
3
  import React from "react";
3
4
  import { InputField } from "./InputField";
4
5
  import { globalApp } from "./app/ReactApp";
5
6
  import { VBox } from "./FlexBox";
6
- import { MUUtils } from "./MUUtils";
7
7
  /**
8
8
  * Quick list
9
9
  * @param props Props
@@ -11,7 +11,7 @@ import { MUUtils } from "./MUUtils";
11
11
  */
12
12
  export function QuickList(props) {
13
13
  // Destruct
14
- const { buttonProps = {}, label, inputProps, itemLabel = MUUtils.getListItemLabel, 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 { buttonProps = {}, label, inputProps, itemLabel = DataTypes.getListItemLabel, itemRenderer = (item) => itemLabel(item), itemProps, loadData, noMatchesLabel = globalApp === null || globalApp === void 0 ? void 0 : globalApp.get("noMatches"), gap = 1, height = "480px", onItemClick, ...rest } = props;
15
15
  const { onClick, ...buttonRest } = buttonProps;
16
16
  // States
17
17
  const [loading, setLoading] = React.useState(false);
package/lib/TagListPro.js CHANGED
@@ -4,12 +4,13 @@ import CheckBoxIcon from "@mui/icons-material/CheckBox";
4
4
  import React from "react";
5
5
  import { InputField } from "./InputField";
6
6
  import { globalApp } from "./app/ReactApp";
7
+ import { DataTypes } from "@etsoo/shared";
7
8
  export function TagListPro(props) {
8
9
  var _a;
9
10
  // Labels
10
11
  const { noOptions, loading: loadingLabel, more = "More", open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "more", "open")) !== null && _a !== void 0 ? _a : {};
11
12
  const moreLabel = more + "...";
12
- const getLabel = (item) => "label" in item ? item.label : "name" in item ? item.name : "";
13
+ const getLabel = (item) => DataTypes.getListItemLabel(item);
13
14
  // Destruct
14
15
  const { renderOption = (props, option, { selected }) => (React.createElement("li", { ...props },
15
16
  React.createElement(React.Fragment, null,
package/lib/Tiplist.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DataTypes, IdDefaultType, ListType } from "@etsoo/shared";
1
+ import { DataTypes, IdDefaultType, ListType2 } from "@etsoo/shared";
2
2
  import React from "react";
3
3
  import { AutocompleteExtendedProps } from "./AutocompleteExtendedProps";
4
4
  /**
@@ -23,4 +23,4 @@ export type TiplistProps<T extends object, D extends DataTypes.Keys<T>> = Omit<A
23
23
  * @param props Props
24
24
  * @returns Component
25
25
  */
26
- export declare function Tiplist<T extends object = ListType, D extends DataTypes.Keys<T> = IdDefaultType<T>>(props: TiplistProps<T, D>): React.JSX.Element;
26
+ export declare function Tiplist<T extends object = ListType2, D extends DataTypes.Keys<T> = IdDefaultType<T>>(props: TiplistProps<T, D>): React.JSX.Element;
package/lib/Tiplist.js CHANGED
@@ -203,10 +203,6 @@ export function Tiplist(props) {
203
203
  return (more !== null && more !== void 0 ? more : "More") + "...";
204
204
  return getOptionLabel
205
205
  ? getOptionLabel(item)
206
- : "label" in item
207
- ? `${item.label}`
208
- : "name" in item
209
- ? `${item.name}`
210
- : `${item}`;
206
+ : DataTypes.getObjectItemLabel(item);
211
207
  }, ...rest })));
212
208
  }
package/lib/TiplistPro.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ReactUtils, useDelayedExecutor } from "@etsoo/react";
2
+ import { DataTypes } from "@etsoo/shared";
2
3
  import { Autocomplete } from "@mui/material";
3
4
  import React from "react";
4
5
  import { InputField } from "./InputField";
5
6
  import { globalApp } from "./app/ReactApp";
6
- import { MUUtils } from "./MUUtils";
7
7
  /**
8
8
  * TiplistPro
9
9
  * @param props Props
@@ -196,7 +196,7 @@ export function TiplistPro(props) {
196
196
  if (item["id"] === -1)
197
197
  return (more !== null && more !== void 0 ? more : "More") + "...";
198
198
  if (getOptionLabel == null)
199
- return MUUtils.getListItemLabel(item);
199
+ return DataTypes.getListItemLabel(item);
200
200
  return getOptionLabel(item);
201
201
  }, ...rest })));
202
202
  }
@@ -1,9 +1,9 @@
1
- import { IAppSettings } from '@etsoo/appscript';
2
- import { DataTypes } from '@etsoo/shared';
1
+ import { IAppSettings } from "@etsoo/appscript";
2
+ import { IdType } from "@etsoo/shared";
3
3
  /**
4
4
  * Service app settings interface
5
5
  */
6
- export interface IServiceAppSettings<S extends DataTypes.IdType = number> extends IAppSettings {
6
+ export interface IServiceAppSettings<S extends IdType = number> extends IAppSettings {
7
7
  /**
8
8
  * Service id
9
9
  */
@@ -1,4 +1,5 @@
1
- import { IActionResult, IUser } from "@etsoo/appscript";
1
+ import { IUser } from "@etsoo/appscript";
2
+ import { IActionResult } from "@etsoo/shared";
2
3
  /**
3
4
  * Service user interface
4
5
  */
@@ -1,4 +1,5 @@
1
- import { IActionResult, IUser } from "@etsoo/appscript";
1
+ import { IUser } from "@etsoo/appscript";
2
+ import { IActionResult } from "@etsoo/shared";
2
3
  /**
3
4
  * SmartERP user interface
4
5
  */
@@ -1,6 +1,6 @@
1
- import { CoreApp, IActionResult, IApp, IAppSettings, ICoreApp, IUser } from "@etsoo/appscript";
1
+ import { CoreApp, IApp, IAppSettings, ICoreApp, IUser } from "@etsoo/appscript";
2
2
  import { INotifier, NotificationReturn } from "@etsoo/notificationbase";
3
- import { DataTypes } from "@etsoo/shared";
3
+ import { DataTypes, IActionResult } from "@etsoo/shared";
4
4
  import React from "react";
5
5
  import { CultureAction, CultureState, INotificationReact, InputDialogProps, IPageData, IStateProps, NotificationReactCallProps, PageAction, PageState, UserAction, UserState } from "@etsoo/react";
6
6
  import { NavigateFunction, NavigateOptions } from "react-router-dom";
package/lib/index.d.ts CHANGED
@@ -82,6 +82,7 @@ export * from "./NotifierPopupProps";
82
82
  export * from "./NumberInputField";
83
83
  export * from "./OptionBool";
84
84
  export * from "./OptionGroup";
85
+ export * from "./OptionGroupFlag";
85
86
  export * from "./PercentCircularProgress";
86
87
  export * from "./PercentLinearProgress";
87
88
  export * from "./PList";
package/lib/index.js CHANGED
@@ -82,6 +82,7 @@ export * from "./NotifierPopupProps";
82
82
  export * from "./NumberInputField";
83
83
  export * from "./OptionBool";
84
84
  export * from "./OptionGroup";
85
+ export * from "./OptionGroupFlag";
85
86
  export * from "./PercentCircularProgress";
86
87
  export * from "./PercentLinearProgress";
87
88
  export * from "./PList";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.3.31",
3
+ "version": "1.3.33",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -45,24 +45,24 @@
45
45
  },
46
46
  "homepage": "https://github.com/ETSOO/ReactMU#readme",
47
47
  "dependencies": {
48
- "@dnd-kit/core": "^6.0.8",
49
- "@dnd-kit/sortable": "^7.0.2",
48
+ "@dnd-kit/core": "^6.1.0",
49
+ "@dnd-kit/sortable": "^8.0.0",
50
50
  "@emotion/css": "^11.11.2",
51
51
  "@emotion/react": "^11.11.1",
52
52
  "@emotion/styled": "^11.11.0",
53
- "@etsoo/appscript": "^1.4.62",
54
- "@etsoo/notificationbase": "^1.1.30",
55
- "@etsoo/react": "^1.7.21",
56
- "@etsoo/shared": "^1.2.18",
53
+ "@etsoo/appscript": "^1.4.72",
54
+ "@etsoo/notificationbase": "^1.1.32",
55
+ "@etsoo/react": "^1.7.24",
56
+ "@etsoo/shared": "^1.2.22",
57
57
  "@mui/icons-material": "^5.14.16",
58
- "@mui/material": "^5.14.16",
59
- "@mui/x-data-grid": "^6.17.0",
60
- "@types/pica": "^9.0.3",
61
- "@types/pulltorefreshjs": "^0.1.6",
62
- "@types/react": "^18.2.33",
63
- "@types/react-avatar-editor": "^13.0.1",
64
- "@types/react-dom": "^18.2.14",
65
- "@types/react-input-mask": "^3.0.4",
58
+ "@mui/material": "^5.14.17",
59
+ "@mui/x-data-grid": "^6.18.1",
60
+ "@types/pica": "^9.0.4",
61
+ "@types/pulltorefreshjs": "^0.1.7",
62
+ "@types/react": "^18.2.37",
63
+ "@types/react-avatar-editor": "^13.0.2",
64
+ "@types/react-dom": "^18.2.15",
65
+ "@types/react-input-mask": "^3.0.5",
66
66
  "chart.js": "^4.4.0",
67
67
  "chartjs-plugin-datalabels": "^2.2.0",
68
68
  "pica": "^9.0.1",
@@ -76,17 +76,17 @@
76
76
  },
77
77
  "devDependencies": {
78
78
  "@babel/cli": "^7.23.0",
79
- "@babel/core": "^7.23.2",
80
- "@babel/plugin-transform-runtime": "^7.23.2",
81
- "@babel/preset-env": "^7.23.2",
82
- "@babel/preset-react": "^7.22.15",
83
- "@babel/preset-typescript": "^7.23.2",
79
+ "@babel/core": "^7.23.3",
80
+ "@babel/plugin-transform-runtime": "^7.23.3",
81
+ "@babel/preset-env": "^7.23.3",
82
+ "@babel/preset-react": "^7.23.3",
83
+ "@babel/preset-typescript": "^7.23.3",
84
84
  "@babel/runtime-corejs3": "^7.23.2",
85
85
  "@testing-library/jest-dom": "^6.1.4",
86
- "@testing-library/react": "^14.0.0",
87
- "@types/jest": "^29.5.7",
88
- "@typescript-eslint/eslint-plugin": "^6.9.1",
89
- "@typescript-eslint/parser": "^6.9.1",
86
+ "@testing-library/react": "^14.1.0",
87
+ "@types/jest": "^29.5.8",
88
+ "@typescript-eslint/eslint-plugin": "^6.10.0",
89
+ "@typescript-eslint/parser": "^6.10.0",
90
90
  "jest": "^29.7.0",
91
91
  "jest-environment-jsdom": "^29.7.0",
92
92
  "typescript": "^5.2.2"
@@ -2,8 +2,7 @@ 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";
6
- import { MUUtils } from "./MUUtils";
5
+ import { DataTypes, ListType2 } from "@etsoo/shared";
7
6
 
8
7
  export type ComboBoxProProps<D extends ListType2 = ListType2> = Omit<
9
8
  AutocompleteProps<D, false, false, true>,
@@ -131,7 +130,7 @@ export function ComboBoxPro<D extends ListType2 = ListType2>(
131
130
  />
132
131
  )}
133
132
  getOptionLabel={(item) =>
134
- typeof item === "object" ? MUUtils.getListItemLabel(item) : item
133
+ typeof item === "object" ? DataTypes.getListItemLabel(item) : item
135
134
  }
136
135
  isOptionEqualToValue={(option, value) => option.id === value.id}
137
136
  noOptionsText={noOptionsText}
package/src/MUUtils.ts CHANGED
@@ -1,23 +1,9 @@
1
- import { ListType2 } from "@etsoo/shared";
2
1
  import { GridApiCommunity } from "@mui/x-data-grid/models/api/gridApiCommunity";
3
2
 
4
3
  /**
5
4
  * MU utilities
6
5
  */
7
6
  export namespace MUUtils {
8
- /**
9
- * Get ListType2 item label
10
- * @param item Item
11
- * @returns Result
12
- */
13
- export function getListItemLabel(item: ListType2) {
14
- return "label" in item
15
- ? item.label
16
- : "name" in item
17
- ? item.name
18
- : item.title;
19
- }
20
-
21
7
  /**
22
8
  * Get grid data
23
9
  * @param grid Grid
@@ -0,0 +1,278 @@
1
+ import {
2
+ DataTypes,
3
+ IdDefaultType,
4
+ LabelDefaultType,
5
+ ListType,
6
+ Utils
7
+ } from "@etsoo/shared";
8
+ import {
9
+ Box,
10
+ Checkbox,
11
+ FormControl,
12
+ FormControlLabel,
13
+ FormControlProps,
14
+ FormGroup,
15
+ FormHelperText,
16
+ InputLabel
17
+ } from "@mui/material";
18
+ import NotchedOutline from "@mui/material/OutlinedInput";
19
+ import React from "react";
20
+
21
+ /**
22
+ * OptionGroupFlag methods ref
23
+ */
24
+ export interface OptionGroupFlagRef {
25
+ /**
26
+ * Disable specific items with their ids
27
+ * @param ids Ids
28
+ */
29
+ disable(ids: number[]): void;
30
+ }
31
+
32
+ /**
33
+ * OptionGroupFlag props
34
+ */
35
+ export type OptionGroupFlagProps<
36
+ T extends object,
37
+ D extends DataTypes.Keys<T, number>,
38
+ L extends DataTypes.Keys<T, string>
39
+ > = Omit<FormControlProps<"fieldset">, "defaultValue"> & {
40
+ /**
41
+ * Default value
42
+ */
43
+ defaultValue?: T[D] & number;
44
+
45
+ /**
46
+ * Get option label function
47
+ */
48
+ getOptionLabel?: (option: T) => string;
49
+
50
+ /**
51
+ * Id field
52
+ */
53
+ idField?: D;
54
+
55
+ /**
56
+ * Label
57
+ */
58
+ label?: string;
59
+
60
+ /**
61
+ * Label field
62
+ */
63
+ labelField?: L;
64
+
65
+ /**
66
+ * Methods
67
+ */
68
+ mRef?: React.Ref<OptionGroupFlagRef>;
69
+
70
+ /**
71
+ * Field name
72
+ */
73
+ name: string;
74
+
75
+ /**
76
+ * On value change handler
77
+ */
78
+ onValueChange?: (value?: T[D] & number) => void;
79
+
80
+ /**
81
+ * Array of options.
82
+ */
83
+ options: ReadonlyArray<T>;
84
+
85
+ /**
86
+ * Is the field read only?
87
+ */
88
+ readOnly?: boolean;
89
+
90
+ /**
91
+ * Display group of elements in a compact row
92
+ */
93
+ row?: boolean;
94
+
95
+ /**
96
+ * Item size
97
+ */
98
+ itemSize?: "small" | "medium";
99
+
100
+ /**
101
+ * Item height in px
102
+ */
103
+ itemHeight?: number;
104
+
105
+ /**
106
+ * Helper text
107
+ */
108
+ helperText?: React.ReactNode;
109
+ };
110
+
111
+ /**
112
+ * OptionGroupFlag
113
+ * @param props Props
114
+ * @returns Component
115
+ */
116
+ export function OptionGroupFlag<
117
+ T extends object = ListType,
118
+ D extends DataTypes.Keys<T, number> = IdDefaultType<T, number>,
119
+ L extends DataTypes.Keys<T, string> = LabelDefaultType<T>
120
+ >(props: OptionGroupFlagProps<T, D, L>) {
121
+ // Destruct
122
+ const {
123
+ getOptionLabel,
124
+ defaultValue,
125
+ idField = "id" as D,
126
+ label,
127
+ labelField = "label" as L,
128
+ mRef,
129
+ name,
130
+ onValueChange,
131
+ options,
132
+ readOnly,
133
+ row,
134
+ itemSize,
135
+ itemHeight = row ? 56 : 42,
136
+ helperText,
137
+ variant,
138
+ required,
139
+ fullWidth,
140
+ sx = {},
141
+ ...rest
142
+ } = props;
143
+
144
+ // Outlined
145
+ const outlined = variant === "outlined";
146
+
147
+ if (sx) {
148
+ Object.assign(sx, {
149
+ height: outlined
150
+ ? row
151
+ ? `${itemHeight}px`
152
+ : `${options.length * itemHeight + 14}px`
153
+ : undefined
154
+ });
155
+ }
156
+
157
+ // Get option value
158
+ // D type should be the source id type
159
+ const getOptionValue = (option: T): (T[D] & number) | null => {
160
+ const value = DataTypes.getValue(option, idField);
161
+ if (value == null) return null;
162
+ return value as T[D] & number;
163
+ };
164
+
165
+ // Value
166
+ const [value, setValue] = React.useState(defaultValue);
167
+
168
+ React.useEffect(() => {
169
+ setValue(defaultValue);
170
+ }, [defaultValue]);
171
+
172
+ // Disabled ids
173
+ const [disabledIds, setDisabledIds] = React.useState<number[]>();
174
+
175
+ // Item checked
176
+ const itemChecked = (option: T) => {
177
+ // Value
178
+ const itemValue = getOptionValue(option);
179
+ if (itemValue == null || value == null) return false;
180
+
181
+ return (value & itemValue) > 0;
182
+ };
183
+
184
+ React.useImperativeHandle(mRef, () => ({
185
+ disable(ids: number[]) {
186
+ setDisabledIds(ids);
187
+ }
188
+ }));
189
+
190
+ // First item value
191
+ const firstOptionValue = getOptionValue(options[0]);
192
+
193
+ // Items
194
+ const list = options.map((option) => {
195
+ // Value
196
+ const ov = getOptionValue(option);
197
+ if (ov == null) return;
198
+
199
+ // Control
200
+ const control = (
201
+ <Checkbox
202
+ name={name}
203
+ readOnly={readOnly}
204
+ size={itemSize}
205
+ checked={itemChecked(option)}
206
+ disabled={disabledIds?.includes(ov)}
207
+ onChange={(event) => {
208
+ if (firstOptionValue == null) return;
209
+
210
+ const typeValue = Utils.parseString(
211
+ event.target.value,
212
+ firstOptionValue
213
+ );
214
+
215
+ const newValue = (
216
+ value == null
217
+ ? event.target.checked
218
+ ? typeValue
219
+ : undefined
220
+ : event.target.checked
221
+ ? value | typeValue
222
+ : value ^ typeValue
223
+ ) as (T[D] & number) | undefined;
224
+
225
+ if (onValueChange) onValueChange(newValue);
226
+ setValue(newValue);
227
+ }}
228
+ />
229
+ );
230
+
231
+ // Label
232
+ const label =
233
+ getOptionLabel == null ? `${option[labelField]}` : getOptionLabel(option);
234
+
235
+ return (
236
+ <FormControlLabel key={ov} control={control} value={ov} label={label} />
237
+ );
238
+ });
239
+
240
+ // Layout
241
+ return (
242
+ <React.Fragment>
243
+ <FormControl component="fieldset" fullWidth={fullWidth} sx={sx} {...rest}>
244
+ {label && (
245
+ <InputLabel required={required} variant={variant} shrink>
246
+ {label}
247
+ </InputLabel>
248
+ )}
249
+ {outlined && (
250
+ <NotchedOutline
251
+ label={label && required ? label + " *" : label}
252
+ notched
253
+ sx={{
254
+ cursor: "default",
255
+ position: "absolute",
256
+ width: fullWidth ? "100%" : "auto",
257
+ "& input": {
258
+ visibility: "hidden"
259
+ }
260
+ }}
261
+ />
262
+ )}
263
+ <Box
264
+ paddingLeft={2}
265
+ paddingY="7px"
266
+ position={outlined ? "absolute" : undefined}
267
+ >
268
+ <FormGroup row={row}>{list}</FormGroup>
269
+ </Box>
270
+ </FormControl>
271
+ {helperText && (
272
+ <FormHelperText sx={{ marginLeft: 2, marginRight: 2 }}>
273
+ {helperText}
274
+ </FormHelperText>
275
+ )}
276
+ </React.Fragment>
277
+ );
278
+ }
package/src/QuickList.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { ListType2 } from "@etsoo/shared";
1
+ import { DataTypes, ListType2 } from "@etsoo/shared";
2
2
  import {
3
3
  LinearProgress,
4
4
  List,
@@ -13,7 +13,6 @@ import React from "react";
13
13
  import { InputField, InputFieldProps } from "./InputField";
14
14
  import { globalApp } from "./app/ReactApp";
15
15
  import { VBox } from "./FlexBox";
16
- import { MUUtils } from "./MUUtils";
17
16
 
18
17
  /**
19
18
  * Quick list props
@@ -83,7 +82,7 @@ export function QuickList<T extends ListType2 = ListType2>(
83
82
  buttonProps = {},
84
83
  label,
85
84
  inputProps,
86
- itemLabel = MUUtils.getListItemLabel,
85
+ itemLabel = DataTypes.getListItemLabel,
87
86
  itemRenderer = (item: T) => itemLabel(item),
88
87
  itemProps,
89
88
  loadData,
@@ -4,7 +4,7 @@ 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
+ import { DataTypes, ListType2 } from "@etsoo/shared";
8
8
 
9
9
  export type TagListProProps<D extends ListType2 = ListType2> = Omit<
10
10
  AutocompleteProps<D, true, false, false>,
@@ -47,8 +47,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
47
47
 
48
48
  const moreLabel = more + "...";
49
49
 
50
- const getLabel = (item: D) =>
51
- "label" in item ? item.label : "name" in item ? item.name : "";
50
+ const getLabel = (item: D) => DataTypes.getListItemLabel(item);
52
51
 
53
52
  // Destruct
54
53
  const {
package/src/Tiplist.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactUtils, useDelayedExecutor } from "@etsoo/react";
2
- import { DataTypes, IdDefaultType, ListType } from "@etsoo/shared";
2
+ import { DataTypes, IdDefaultType, ListType2 } from "@etsoo/shared";
3
3
  import { Autocomplete, AutocompleteRenderInputParams } from "@mui/material";
4
4
  import React from "react";
5
5
  import { AutocompleteExtendedProps } from "./AutocompleteExtendedProps";
@@ -48,7 +48,7 @@ interface States<T extends object> {
48
48
  * @returns Component
49
49
  */
50
50
  export function Tiplist<
51
- T extends object = ListType,
51
+ T extends object = ListType2,
52
52
  D extends DataTypes.Keys<T> = IdDefaultType<T>
53
53
  >(props: TiplistProps<T, D>) {
54
54
  // Labels
@@ -373,11 +373,7 @@ export function Tiplist<
373
373
  if (item[idField] === "n/a") return (more ?? "More") + "...";
374
374
  return getOptionLabel
375
375
  ? getOptionLabel(item)
376
- : "label" in item
377
- ? `${item.label}`
378
- : "name" in item
379
- ? `${item.name}`
380
- : `${item}`;
376
+ : DataTypes.getObjectItemLabel(item);
381
377
  }}
382
378
  {...rest}
383
379
  />
@@ -1,10 +1,9 @@
1
1
  import { ReactUtils, useDelayedExecutor } from "@etsoo/react";
2
- import { ListType2 } from "@etsoo/shared";
2
+ import { DataTypes, ListType2 } from "@etsoo/shared";
3
3
  import { Autocomplete, AutocompleteProps } from "@mui/material";
4
4
  import React, { ChangeEventHandler } from "react";
5
5
  import { InputField, InputFieldProps } from "./InputField";
6
6
  import { globalApp } from "./app/ReactApp";
7
- import { MUUtils } from "./MUUtils";
8
7
 
9
8
  /**
10
9
  * TiplistPro props
@@ -370,7 +369,7 @@ export function TiplistPro<T extends ListType2 = ListType2>(
370
369
  getOptionLabel={(item) => {
371
370
  if (typeof item === "string") return item;
372
371
  if (item["id"] === -1) return (more ?? "More") + "...";
373
- if (getOptionLabel == null) return MUUtils.getListItemLabel(item);
372
+ if (getOptionLabel == null) return DataTypes.getListItemLabel(item);
374
373
  return getOptionLabel(item);
375
374
  }}
376
375
  {...rest}
@@ -1,5 +1,4 @@
1
1
  import {
2
- IActionResult,
3
2
  IApiPayload,
4
3
  IAppSettings,
5
4
  IUser,
@@ -9,6 +8,7 @@ import {
9
8
  } from "@etsoo/appscript";
10
9
  import { CoreConstants, IPageData } from "@etsoo/react";
11
10
  import { ReactApp } from "./ReactApp";
11
+ import { IActionResult } from "@etsoo/shared";
12
12
 
13
13
  /**
14
14
  * Common independent application
@@ -1,13 +1,13 @@
1
- import { IAppSettings } from '@etsoo/appscript';
2
- import { DataTypes } from '@etsoo/shared';
1
+ import { IAppSettings } from "@etsoo/appscript";
2
+ import { IdType } from "@etsoo/shared";
3
3
 
4
4
  /**
5
5
  * Service app settings interface
6
6
  */
7
- export interface IServiceAppSettings<S extends DataTypes.IdType = number>
8
- extends IAppSettings {
9
- /**
10
- * Service id
11
- */
12
- readonly serviceId: S;
7
+ export interface IServiceAppSettings<S extends IdType = number>
8
+ extends IAppSettings {
9
+ /**
10
+ * Service id
11
+ */
12
+ readonly serviceId: S;
13
13
  }
@@ -1,4 +1,5 @@
1
- import { IActionResult, IUser } from "@etsoo/appscript";
1
+ import { IUser } from "@etsoo/appscript";
2
+ import { IActionResult } from "@etsoo/shared";
2
3
 
3
4
  /**
4
5
  * Service user interface
@@ -1,4 +1,5 @@
1
- import { IActionResult, IUser } from "@etsoo/appscript";
1
+ import { IUser } from "@etsoo/appscript";
2
+ import { IActionResult } from "@etsoo/shared";
2
3
 
3
4
  /**
4
5
  * SmartERP user interface
@@ -2,7 +2,6 @@ import {
2
2
  BridgeUtils,
3
3
  CoreApp,
4
4
  createClient,
5
- IActionResult,
6
5
  IApp,
7
6
  IAppSettings,
8
7
  ICoreApp,
@@ -14,7 +13,7 @@ import {
14
13
  NotificationRenderProps,
15
14
  NotificationReturn
16
15
  } from "@etsoo/notificationbase";
17
- import { DataTypes, WindowStorage } from "@etsoo/shared";
16
+ import { DataTypes, IActionResult, WindowStorage } from "@etsoo/shared";
18
17
  import React from "react";
19
18
  import { NotifierMU } from "../NotifierMU";
20
19
  import { ProgressCount } from "../ProgressCount";
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  BridgeUtils,
3
3
  createClient,
4
- IActionResult,
5
4
  IApi,
6
5
  IApiPayload,
7
6
  RefreshTokenProps,
@@ -9,7 +8,7 @@ import {
9
8
  RefreshTokenRQ
10
9
  } from "@etsoo/appscript";
11
10
  import { CoreConstants } from "@etsoo/react";
12
- import { DomUtils } from "@etsoo/shared";
11
+ import { DomUtils, IActionResult } from "@etsoo/shared";
13
12
  import { IServiceApp } from "./IServiceApp";
14
13
  import { IServiceAppSettings } from "./IServiceAppSettings";
15
14
  import { IServicePageData } from "./IServicePage";
package/src/index.ts CHANGED
@@ -86,6 +86,7 @@ export * from "./NotifierPopupProps";
86
86
  export * from "./NumberInputField";
87
87
  export * from "./OptionBool";
88
88
  export * from "./OptionGroup";
89
+ export * from "./OptionGroupFlag";
89
90
  export * from "./PercentCircularProgress";
90
91
  export * from "./PercentLinearProgress";
91
92
  export * from "./PList";