@etsoo/materialui 1.0.37 → 1.0.39

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.
@@ -0,0 +1,39 @@
1
+ /// <reference types="react" />
2
+ import { TextFieldProps } from '@mui/material';
3
+ import { InputDialogProps } from '@etsoo/react';
4
+ /**
5
+ * Data step
6
+ */
7
+ export declare type DataStep = Omit<InputDialogProps, 'callback'> & {
8
+ /**
9
+ * Callback
10
+ */
11
+ callback: (form: HTMLFormElement) => boolean | void;
12
+ };
13
+ /**
14
+ * Data collecting steps component props
15
+ */
16
+ export declare type DataStepsProps<T extends object> = Omit<TextFieldProps, 'InputProps' | 'onClick'> & {
17
+ /**
18
+ * JSON value
19
+ */
20
+ jsonValue?: string;
21
+ /**
22
+ * Value formatter
23
+ */
24
+ valueFormatter?: (data: T) => string;
25
+ /**
26
+ * Steps
27
+ */
28
+ steps: (index: number, data: T) => [DataStep, boolean];
29
+ /**
30
+ * On value change handler
31
+ */
32
+ onValueChange?: (value: T) => void;
33
+ };
34
+ /**
35
+ * Data collecting steps component
36
+ * @param props Props
37
+ * @returns Component
38
+ */
39
+ export declare function DataSteps<T extends object>(props: DataStepsProps<T>): JSX.Element;
@@ -0,0 +1,79 @@
1
+ import { Button, IconButton, InputAdornment, TextField } from '@mui/material';
2
+ import CloseIcon from '@mui/icons-material/Close';
3
+ import NavigateNextIcon from '@mui/icons-material/NavigateNext';
4
+ import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore';
5
+ import CheckIcon from '@mui/icons-material/Check';
6
+ import StartIcon from '@mui/icons-material/Start';
7
+ import React from 'react';
8
+ import { globalApp } from './app/ReactApp';
9
+ import { MUGlobal } from './MUGlobal';
10
+ import { HBox } from './FlexBox';
11
+ /**
12
+ * Data collecting steps component
13
+ * @param props Props
14
+ * @returns Component
15
+ */
16
+ export function DataSteps(props) {
17
+ var _a;
18
+ // App
19
+ const app = globalApp;
20
+ // Labels
21
+ const labels = app.getLabels('close', 'nextStep', 'previousStep', 'submit');
22
+ // Destruct
23
+ const { InputLabelProps = {}, jsonValue, valueFormatter = (_data) => '...', onValueChange, steps, value = '', ...rest } = props;
24
+ // Shrink
25
+ (_a = InputLabelProps.shrink) !== null && _a !== void 0 ? _a : (InputLabelProps.shrink = MUGlobal.searchFieldShrink);
26
+ // Current index
27
+ const indexRef = React.useRef(-1);
28
+ // Current data
29
+ const dataRef = React.useRef({});
30
+ // Current value
31
+ const [localValue, setLocalValue] = React.useState(value);
32
+ // Get step
33
+ const showStep = (index) => {
34
+ indexRef.current = index;
35
+ const [{ callback, ...rest }, more] = steps(index, dataRef.current);
36
+ app.showInputDialog({
37
+ ...rest,
38
+ buttons: (n, callback) => (React.createElement(HBox, { paddingLeft: 2, paddingRight: 2, paddingBottom: 2, gap: 2, justifyContent: "space-between" },
39
+ index === 0 ? (React.createElement(Button, { variant: "outlined", startIcon: React.createElement(CloseIcon, null), onClick: () => n.dismiss() }, labels.close)) : (React.createElement(Button, { variant: "outlined", startIcon: React.createElement(NavigateBeforeIcon, null), onClick: () => {
40
+ n.dismiss();
41
+ showStep(indexRef.current - 1);
42
+ } }, labels.previousStep)),
43
+ more ? (React.createElement(Button, { variant: "contained", startIcon: React.createElement(NavigateNextIcon, null), onClick: async (event) => {
44
+ const result = await callback(event);
45
+ if (!result)
46
+ return;
47
+ showStep(indexRef.current + 1);
48
+ } }, labels.nextStep)) : (React.createElement(Button, { variant: "contained", startIcon: React.createElement(CheckIcon, null), onClick: async (event) => {
49
+ const result = await callback(event);
50
+ if (!result)
51
+ return;
52
+ const value = dataRef.current;
53
+ setLocalValue(valueFormatter(value));
54
+ if (onValueChange)
55
+ onValueChange(value);
56
+ } }, labels.submit)))),
57
+ callback: (form) => {
58
+ if (form == null)
59
+ return;
60
+ const result = callback(form);
61
+ if (result !== true) {
62
+ return false;
63
+ }
64
+ }
65
+ });
66
+ };
67
+ React.useEffect(() => {
68
+ if (jsonValue) {
69
+ dataRef.current = JSON.parse(jsonValue);
70
+ setLocalValue(valueFormatter(dataRef.current));
71
+ }
72
+ }, [jsonValue]);
73
+ return (React.createElement(TextField, { InputLabelProps: InputLabelProps, InputProps: {
74
+ readOnly: true,
75
+ endAdornment: (React.createElement(InputAdornment, { position: "end" },
76
+ React.createElement(IconButton, { edge: "end", size: "small" },
77
+ React.createElement(StartIcon, null))))
78
+ }, onClick: () => showStep(0), value: localValue, ...rest }));
79
+ }
package/lib/InputField.js CHANGED
@@ -8,10 +8,11 @@ import { MUGlobal } from './MUGlobal';
8
8
  * @returns Component
9
9
  */
10
10
  export function InputField(props) {
11
+ var _a;
11
12
  // Destruct
12
13
  const { changeDelay, InputLabelProps = {}, InputProps = {}, onChange, readOnly, size = MUGlobal.inputFieldSize, variant = MUGlobal.inputFieldVariant, ...rest } = props;
13
14
  // Shrink
14
- InputLabelProps.shrink = MUGlobal.searchFieldShrink;
15
+ (_a = InputLabelProps.shrink) !== null && _a !== void 0 ? _a : (InputLabelProps.shrink = MUGlobal.searchFieldShrink);
15
16
  // Read only
16
17
  if (readOnly != null)
17
18
  InputProps.readOnly = readOnly;
package/lib/MaskInput.js CHANGED
@@ -9,6 +9,7 @@ import { useIMask } from 'react-imask';
9
9
  * @returns Component
10
10
  */
11
11
  export function MaskInput(props) {
12
+ var _a;
12
13
  // Destruct
13
14
  const { defaultValue, mask, InputLabelProps = {}, InputProps = {}, onAccept, onComplete, readOnly, search = false, size = search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize, value, variant = search
14
15
  ? MUGlobal.searchFieldVariant
@@ -25,9 +26,9 @@ export function MaskInput(props) {
25
26
  });
26
27
  const localValue = defaultValue !== null && defaultValue !== void 0 ? defaultValue : value;
27
28
  // Shrink
28
- InputLabelProps.shrink = search
29
+ (_a = InputLabelProps.shrink) !== null && _a !== void 0 ? _a : (InputLabelProps.shrink = search
29
30
  ? MUGlobal.searchFieldShrink
30
- : MUGlobal.inputFieldShrink;
31
+ : MUGlobal.inputFieldShrink);
31
32
  // Read only
32
33
  if (readOnly != null)
33
34
  InputProps.readOnly = readOnly;
package/lib/NotifierMU.js CHANGED
@@ -55,6 +55,7 @@ export class NotificationMU extends NotificationReact {
55
55
  // Callback
56
56
  const callback = async (_event) => {
57
57
  await this.returnValue(undefined);
58
+ return true;
58
59
  };
59
60
  return (React.createElement(Dialog, { key: this.id, open: this.open, PaperComponent: DraggablePaperComponent, className: className, fullWidth: fullWidth, maxWidth: maxWidth, fullScreen: fullScreen },
60
61
  React.createElement(IconDialogTitle, { className: "draggable-dialog-title" },
@@ -71,7 +72,10 @@ export class NotificationMU extends NotificationReact {
71
72
  const labels = Labels.NotificationMU;
72
73
  const title = (_a = this.title) !== null && _a !== void 0 ? _a : labels.confirmTitle;
73
74
  const { buttons, okLabel = labels.confirmYes, cancelLabel = labels.confirmNo, cancelButton = true, inputs, fullScreen, fullWidth = true, maxWidth, primaryButton } = (_b = this.inputProps) !== null && _b !== void 0 ? _b : {};
74
- const callback = async (_event, value) => await this.returnValue(value);
75
+ const callback = async (_event, value) => {
76
+ await this.returnValue(value);
77
+ return true;
78
+ };
75
79
  return (React.createElement(Dialog, { key: this.id, open: this.open, PaperComponent: DraggablePaperComponent, className: className, fullWidth: fullWidth, maxWidth: maxWidth, fullScreen: fullScreen },
76
80
  React.createElement(IconDialogTitle, { className: "draggable-dialog-title" },
77
81
  React.createElement(Help, { color: "action" }),
@@ -134,7 +138,7 @@ export class NotificationMU extends NotificationReact {
134
138
  const dateValue = input.valueAsDate;
135
139
  if (dateValue == null && input.required) {
136
140
  input.focus();
137
- return;
141
+ return false;
138
142
  }
139
143
  result = this.onReturn(dateValue);
140
144
  }
@@ -142,7 +146,7 @@ export class NotificationMU extends NotificationReact {
142
146
  const numberValue = input.valueAsNumber;
143
147
  if (isNaN(numberValue) && input.required) {
144
148
  input.focus();
145
- return;
149
+ return false;
146
150
  }
147
151
  result = this.onReturn(numberValue);
148
152
  }
@@ -154,7 +158,7 @@ export class NotificationMU extends NotificationReact {
154
158
  const textValue = input.value.trim();
155
159
  if (textValue === '' && input.required) {
156
160
  input.focus();
157
- return;
161
+ return false;
158
162
  }
159
163
  result = this.onReturn(textValue);
160
164
  }
@@ -168,14 +172,15 @@ export class NotificationMU extends NotificationReact {
168
172
  const v = await result;
169
173
  if (v === false) {
170
174
  input === null || input === void 0 ? void 0 : input.focus();
171
- return;
175
+ return false;
172
176
  }
173
177
  if (typeof v === 'string') {
174
178
  setError(v);
175
179
  input === null || input === void 0 ? void 0 : input.focus();
176
- return;
180
+ return false;
177
181
  }
178
182
  this.dismiss();
183
+ return true;
179
184
  };
180
185
  let localInputs;
181
186
  let value = undefined;
@@ -8,10 +8,11 @@ import { MUGlobal } from './MUGlobal';
8
8
  * @returns Component
9
9
  */
10
10
  export function SearchField(props) {
11
+ var _a;
11
12
  // Destruct
12
13
  const { changeDelay, InputLabelProps = {}, InputProps = {}, onChange, readOnly, size = MUGlobal.searchFieldSize, variant = MUGlobal.searchFieldVariant, ...rest } = props;
13
14
  // Shrink
14
- InputLabelProps.shrink = MUGlobal.searchFieldShrink;
15
+ (_a = InputLabelProps.shrink) !== null && _a !== void 0 ? _a : (InputLabelProps.shrink = MUGlobal.searchFieldShrink);
15
16
  // Read only
16
17
  if (readOnly != null)
17
18
  InputProps.readOnly = readOnly;
package/lib/index.d.ts CHANGED
@@ -31,6 +31,7 @@ export * from './CountdownButton';
31
31
  export * from './CustomFabProps';
32
32
  export * from './DataGridEx';
33
33
  export * from './DataGridRenderers';
34
+ export * from './DataSteps';
34
35
  export * from './DialogButton';
35
36
  export * from './DnDList';
36
37
  export * from './DraggablePaperComponent';
package/lib/index.js CHANGED
@@ -31,6 +31,7 @@ export * from './CountdownButton';
31
31
  export * from './CustomFabProps';
32
32
  export * from './DataGridEx';
33
33
  export * from './DataGridRenderers';
34
+ export * from './DataSteps';
34
35
  export * from './DialogButton';
35
36
  export * from './DnDList';
36
37
  export * from './DraggablePaperComponent';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.0.37",
3
+ "version": "1.0.39",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -51,10 +51,10 @@
51
51
  "@emotion/css": "^11.10.0",
52
52
  "@emotion/react": "^11.10.4",
53
53
  "@emotion/styled": "^11.10.4",
54
- "@etsoo/appscript": "^1.3.0",
55
- "@etsoo/notificationbase": "^1.1.11",
56
- "@etsoo/react": "^1.6.10",
57
- "@etsoo/shared": "^1.1.58",
54
+ "@etsoo/appscript": "^1.3.1",
55
+ "@etsoo/notificationbase": "^1.1.12",
56
+ "@etsoo/react": "^1.6.12",
57
+ "@etsoo/shared": "^1.1.59",
58
58
  "@mui/icons-material": "^5.10.6",
59
59
  "@mui/material": "^5.10.7",
60
60
  "@types/pica": "^9.0.1",
@@ -82,16 +82,16 @@
82
82
  "@babel/runtime-corejs3": "^7.19.1",
83
83
  "@testing-library/jest-dom": "^5.16.5",
84
84
  "@testing-library/react": "^13.4.0",
85
- "@types/jest": "^29.0.3",
85
+ "@types/jest": "^29.1.1",
86
86
  "@typescript-eslint/eslint-plugin": "^5.38.1",
87
87
  "@typescript-eslint/parser": "^5.38.1",
88
88
  "eslint": "^8.24.0",
89
89
  "eslint-config-airbnb-base": "^15.0.0",
90
90
  "eslint-plugin-import": "^2.26.0",
91
91
  "eslint-plugin-react": "^7.31.8",
92
- "jest": "^29.0.3",
93
- "jest-environment-jsdom": "^29.0.3",
94
- "ts-jest": "^29.0.2",
92
+ "jest": "^29.1.2",
93
+ "jest-environment-jsdom": "^29.1.2",
94
+ "ts-jest": "^29.0.3",
95
95
  "typescript": "^4.8.4"
96
96
  }
97
97
  }
@@ -0,0 +1,194 @@
1
+ import {
2
+ Button,
3
+ IconButton,
4
+ InputAdornment,
5
+ TextField,
6
+ TextFieldProps
7
+ } from '@mui/material';
8
+ import CloseIcon from '@mui/icons-material/Close';
9
+ import NavigateNextIcon from '@mui/icons-material/NavigateNext';
10
+ import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore';
11
+ import CheckIcon from '@mui/icons-material/Check';
12
+ import StartIcon from '@mui/icons-material/Start';
13
+ import { InputDialogProps } from '@etsoo/react';
14
+ import React from 'react';
15
+ import { globalApp } from './app/ReactApp';
16
+ import { MUGlobal } from './MUGlobal';
17
+ import { HBox } from './FlexBox';
18
+
19
+ /**
20
+ * Data step
21
+ */
22
+ export type DataStep = Omit<InputDialogProps, 'callback'> & {
23
+ /**
24
+ * Callback
25
+ */
26
+ callback: (form: HTMLFormElement) => boolean | void;
27
+ };
28
+
29
+ /**
30
+ * Data collecting steps component props
31
+ */
32
+ export type DataStepsProps<T extends object> = Omit<
33
+ TextFieldProps,
34
+ 'InputProps' | 'onClick'
35
+ > & {
36
+ /**
37
+ * JSON value
38
+ */
39
+ jsonValue?: string;
40
+
41
+ /**
42
+ * Value formatter
43
+ */
44
+ valueFormatter?: (data: T) => string;
45
+
46
+ /**
47
+ * Steps
48
+ */
49
+ steps: (index: number, data: T) => [DataStep, boolean];
50
+
51
+ /**
52
+ * On value change handler
53
+ */
54
+ onValueChange?: (value: T) => void;
55
+ };
56
+
57
+ /**
58
+ * Data collecting steps component
59
+ * @param props Props
60
+ * @returns Component
61
+ */
62
+ export function DataSteps<T extends object>(props: DataStepsProps<T>) {
63
+ // App
64
+ const app = globalApp;
65
+
66
+ // Labels
67
+ const labels = app.getLabels('close', 'nextStep', 'previousStep', 'submit');
68
+
69
+ // Destruct
70
+ const {
71
+ InputLabelProps = {},
72
+ jsonValue,
73
+ valueFormatter = (_data: T) => '...',
74
+ onValueChange,
75
+ steps,
76
+ value = '',
77
+ ...rest
78
+ } = props;
79
+
80
+ // Shrink
81
+ InputLabelProps.shrink ??= MUGlobal.searchFieldShrink;
82
+
83
+ // Current index
84
+ const indexRef = React.useRef<number>(-1);
85
+
86
+ // Current data
87
+ const dataRef = React.useRef({} as T);
88
+
89
+ // Current value
90
+ const [localValue, setLocalValue] = React.useState(value);
91
+
92
+ // Get step
93
+ const showStep = (index: number) => {
94
+ indexRef.current = index;
95
+ const [{ callback, ...rest }, more] = steps(index, dataRef.current);
96
+
97
+ app.showInputDialog({
98
+ ...rest,
99
+ buttons: (n, callback) => (
100
+ <HBox
101
+ paddingLeft={2}
102
+ paddingRight={2}
103
+ paddingBottom={2}
104
+ gap={2}
105
+ justifyContent="space-between"
106
+ >
107
+ {index === 0 ? (
108
+ <Button
109
+ variant="outlined"
110
+ startIcon={<CloseIcon />}
111
+ onClick={() => n.dismiss()}
112
+ >
113
+ {labels.close}
114
+ </Button>
115
+ ) : (
116
+ <Button
117
+ variant="outlined"
118
+ startIcon={<NavigateBeforeIcon />}
119
+ onClick={() => {
120
+ n.dismiss();
121
+ showStep(indexRef.current - 1);
122
+ }}
123
+ >
124
+ {labels.previousStep}
125
+ </Button>
126
+ )}
127
+
128
+ {more ? (
129
+ <Button
130
+ variant="contained"
131
+ startIcon={<NavigateNextIcon />}
132
+ onClick={async (event) => {
133
+ const result = await callback(event);
134
+ if (!result) return;
135
+ showStep(indexRef.current + 1);
136
+ }}
137
+ >
138
+ {labels.nextStep}
139
+ </Button>
140
+ ) : (
141
+ <Button
142
+ variant="contained"
143
+ startIcon={<CheckIcon />}
144
+ onClick={async (event) => {
145
+ const result = await callback(event);
146
+ if (!result) return;
147
+
148
+ const value = dataRef.current;
149
+ setLocalValue(valueFormatter(value));
150
+
151
+ if (onValueChange) onValueChange(value);
152
+ }}
153
+ >
154
+ {labels.submit}
155
+ </Button>
156
+ )}
157
+ </HBox>
158
+ ),
159
+ callback: (form) => {
160
+ if (form == null) return;
161
+ const result = callback(form);
162
+ if (result !== true) {
163
+ return false;
164
+ }
165
+ }
166
+ });
167
+ };
168
+
169
+ React.useEffect(() => {
170
+ if (jsonValue) {
171
+ dataRef.current = JSON.parse(jsonValue);
172
+ setLocalValue(valueFormatter(dataRef.current));
173
+ }
174
+ }, [jsonValue]);
175
+
176
+ return (
177
+ <TextField
178
+ InputLabelProps={InputLabelProps}
179
+ InputProps={{
180
+ readOnly: true,
181
+ endAdornment: (
182
+ <InputAdornment position="end">
183
+ <IconButton edge="end" size="small">
184
+ <StartIcon />
185
+ </IconButton>
186
+ </InputAdornment>
187
+ )
188
+ }}
189
+ onClick={() => showStep(0)}
190
+ value={localValue}
191
+ {...rest}
192
+ />
193
+ );
194
+ }
@@ -37,7 +37,7 @@ export function InputField(props: InputFieldProps) {
37
37
  } = props;
38
38
 
39
39
  // Shrink
40
- InputLabelProps.shrink = MUGlobal.searchFieldShrink;
40
+ InputLabelProps.shrink ??= MUGlobal.searchFieldShrink;
41
41
 
42
42
  // Read only
43
43
  if (readOnly != null) InputProps.readOnly = readOnly;
package/src/MaskInput.tsx CHANGED
@@ -80,7 +80,7 @@ export function MaskInput<
80
80
  const localValue = defaultValue ?? value;
81
81
 
82
82
  // Shrink
83
- InputLabelProps.shrink = search
83
+ InputLabelProps.shrink ??= search
84
84
  ? MUGlobal.searchFieldShrink
85
85
  : MUGlobal.inputFieldShrink;
86
86
 
@@ -100,6 +100,7 @@ export class NotificationMU extends NotificationReact {
100
100
  _event: React.MouseEvent<HTMLButtonElement>
101
101
  ) => {
102
102
  await this.returnValue(undefined);
103
+ return true;
103
104
  };
104
105
 
105
106
  return (
@@ -158,7 +159,10 @@ export class NotificationMU extends NotificationReact {
158
159
  const callback = async (
159
160
  _event: React.MouseEvent<HTMLButtonElement>,
160
161
  value: boolean
161
- ) => await this.returnValue(value);
162
+ ) => {
163
+ await this.returnValue(value);
164
+ return true;
165
+ };
162
166
 
163
167
  return (
164
168
  <Dialog
@@ -291,14 +295,14 @@ export class NotificationMU extends NotificationReact {
291
295
  const dateValue = input.valueAsDate;
292
296
  if (dateValue == null && input.required) {
293
297
  input.focus();
294
- return;
298
+ return false;
295
299
  }
296
300
  result = this.onReturn(dateValue);
297
301
  } else if (type === 'number') {
298
302
  const numberValue = input.valueAsNumber;
299
303
  if (isNaN(numberValue) && input.required) {
300
304
  input.focus();
301
- return;
305
+ return false;
302
306
  }
303
307
  result = this.onReturn(numberValue);
304
308
  } else if (type === 'switch') {
@@ -308,7 +312,7 @@ export class NotificationMU extends NotificationReact {
308
312
  const textValue = input.value.trim();
309
313
  if (textValue === '' && input.required) {
310
314
  input.focus();
311
- return;
315
+ return false;
312
316
  }
313
317
  result = this.onReturn(textValue);
314
318
  }
@@ -322,15 +326,16 @@ export class NotificationMU extends NotificationReact {
322
326
  const v = await result;
323
327
  if (v === false) {
324
328
  input?.focus();
325
- return;
329
+ return false;
326
330
  }
327
331
  if (typeof v === 'string') {
328
332
  setError(v);
329
333
  input?.focus();
330
- return;
334
+ return false;
331
335
  }
332
336
 
333
337
  this.dismiss();
338
+ return true;
334
339
  };
335
340
 
336
341
  let localInputs: React.ReactNode;
@@ -37,7 +37,7 @@ export function SearchField(props: SearchFieldProps) {
37
37
  } = props;
38
38
 
39
39
  // Shrink
40
- InputLabelProps.shrink = MUGlobal.searchFieldShrink;
40
+ InputLabelProps.shrink ??= MUGlobal.searchFieldShrink;
41
41
 
42
42
  // Read only
43
43
  if (readOnly != null) InputProps.readOnly = readOnly;
package/src/index.ts CHANGED
@@ -34,6 +34,7 @@ export * from './CountdownButton';
34
34
  export * from './CustomFabProps';
35
35
  export * from './DataGridEx';
36
36
  export * from './DataGridRenderers';
37
+ export * from './DataSteps';
37
38
  export * from './DialogButton';
38
39
  export * from './DnDList';
39
40
  export * from './DraggablePaperComponent';